﻿#region license
// Copyright (C) 2020 ClassicUO Development Community on Github
// 
// This project is an alternative client for the game Ultima Online.
// The goal of this is to develop a lightweight client considering
// new technologies.
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#endregion

using System;
using System.Collections.Generic;
using ClassicUO.Configuration;
using ClassicUO.Game.Managers;
using ClassicUO.IO;
using ClassicUO.IO.Resources;
using ClassicUO.Renderer;
using ClassicUO.Utility.Coroutines;
using ClassicUO.Utility.Logging;
using Microsoft.Xna.Framework;
using SDL2;
using IUpdateable = ClassicUO.Interfaces.IUpdateable;

namespace ClassicUO.Game.Scenes
{
    internal abstract class Scene : IUpdateable, IDisposable
    {
        protected Scene(int sceneID,  bool canresize, bool maximized, bool loadaudio)
        {
            CanResize = canresize;
            CanBeMaximized = maximized;
            CanLoadAudio = loadaudio;
        }

        public readonly bool CanResize, CanBeMaximized, CanLoadAudio;
        public readonly int ID;

        public bool IsDestroyed { get; private set; }

        public bool IsLoaded { get; private set; }

        public int RenderedObjectsCount { get; protected set; }

        public CoroutineManager Coroutines { get; } = new CoroutineManager();

        public AudioManager Audio { get; private set; }

        public virtual void Update(double totalMS, double frameMS)
        {
            Audio?.Update();
            Coroutines.Update();
        }

        public virtual void FixedUpdate(double totalMS, double frameMS)
        {

        }

        public virtual void Dispose()
        {
            if (IsDestroyed)
                return;

            IsDestroyed = true;
            Unload();
        }


        public virtual void Load()
        {
            if (CanLoadAudio)
            {
                Audio = new AudioManager();
                Audio.Initialize();
                Coroutine.Start(this, CleaningResources(), "cleaning resources");
            }

            IsLoaded = true;
        }

        public virtual void Unload()
        {
            Audio?.StopMusic();
            Coroutines.Clear();
        }

        public virtual bool Draw(UltimaBatcher2D batcher)
        {
            return true;
        }


        internal virtual void OnLeftMouseUp() { }
        internal virtual void OnLeftMouseDown() { }

        internal virtual void OnRightMouseUp() { }
        internal virtual void OnRightMouseDown() { }

        internal virtual void OnMiddleMouseUp() { }
        internal virtual void OnMiddleMouseDown() { }


        internal virtual bool OnLeftMouseDoubleClick() => false;
        internal virtual bool OnRightMouseDoubleClick() => false;
        internal virtual bool OnMiddleMouseDoubleClick() => false;
        internal virtual void OnMouseWheel(bool up) { }
        internal virtual void OnMouseDragging() { }
        internal virtual void OnTextInput(string text) { }
        internal virtual void OnKeyDown(SDL.SDL_KeyboardEvent e) { }
        internal virtual void OnKeyUp(SDL.SDL_KeyboardEvent e) { }


        private IEnumerable<IWaitCondition> CleaningResources()
        {
            Log.Trace( "Cleaning routine running...");

            yield return new WaitTime(TimeSpan.FromMilliseconds(10000));

            while (!IsDestroyed)
            {
                ArtLoader.Instance.CleaUnusedResources(Constants.MAX_ART_OBJECT_REMOVED_BY_GARBAGE_COLLECTOR);

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));

                GumpsLoader.Instance.CleaUnusedResources(Constants.MAX_GUMP_OBJECT_REMOVED_BY_GARBAGE_COLLECTOR);

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));

                TexmapsLoader.Instance.CleaUnusedResources(Constants.MAX_ART_OBJECT_REMOVED_BY_GARBAGE_COLLECTOR);

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));

                AnimationsLoader.Instance.CleaUnusedResources(Constants.MAX_ANIMATIONS_OBJECT_REMOVED_BY_GARBAGE_COLLECTOR);

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));

                World.Map?.ClearUnusedBlocks();

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));

                LightsLoader.Instance.CleaUnusedResources(20);

                yield return new WaitTime(TimeSpan.FromMilliseconds(500));
            }

            Log.Trace( "Cleaning routine finished");
        }
    }
}